home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
edit
/
mg2a_src.zip
/
SEARCH.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-03-10
|
15KB
|
669 lines
/*
* Search commands.
* The functions in this file implement the
* search commands (both plain and incremental searches
* are supported) and the query-replace command.
*
* The plain old search code is part of the original
* MicroEMACS "distribution". The incremental search code,
* and the query-replace code, is by Rich Ellison.
*/
#include "def.h"
#ifndef NO_MACRO
#include "macro.h"
#endif
#define SRCH_BEGIN (0) /* Search sub-codes. */
#define SRCH_FORW (-1)
#define SRCH_BACK (-2)
#define SRCH_NOPR (-3)
#define SRCH_ACCM (-4)
#define SRCH_MARK (-5)
typedef struct {
int s_code;
LINE *s_dotp;
int s_doto;
} SRCHCOM;
static SRCHCOM cmds[NSRCH];
static int cip;
int srch_lastdir = SRCH_NOPR; /* Last search flags. */
static VOID is_cpush();
static VOID is_lpush();
static VOID is_pop();
static int is_peek();
static VOID is_undo();
static int is_find();
static VOID is_prompt();
static VOID is_dspl();
static int eq();
/*
* Search forward.
* Get a search string from the user, and search for it,
* starting at ".". If found, "." gets moved to just after the
* matched characters, and display does all the hard stuff.
* If not found, it just prints a message.
*/
/*ARGSUSED*/
forwsearch(f, n)
{
register int s;
if ((s=readpattern("Search")) != TRUE)
return s;
if (forwsrch() == FALSE) {
ewprintf("Search failed: \"%s\"", pat);
return FALSE;
}
srch_lastdir = SRCH_FORW;
return TRUE;
}
/*
* Reverse search.
* Get a search string from the user, and search, starting at "."
* and proceeding toward the front of the buffer. If found "." is left
* pointing at the first character of the pattern [the last character that
* was matched].
*/
/*ARGSUSED*/
backsearch(f, n)
{
register int s;
if ((s=readpattern("Search backward")) != TRUE)
return (s);
if (backsrch() == FALSE) {
ewprintf("Search failed: \"%s\"", pat);
return FALSE;
}
srch_lastdir = SRCH_BACK;
return TRUE;
}
/*
* Search again, using the same search string
* and direction as the last search command. The direction
* has been saved in "srch_lastdir", so you know which way
* to go.
*/
/*ARGSUSED*/
searchagain(f, n)
{
if (srch_lastdir == SRCH_FORW) {
if (forwsrch() == FALSE) {
ewprintf("Search failed: \"%s\"", pat);
return FALSE;
}
return TRUE;
}
if (srch_lastdir == SRCH_BACK) {
if (backsrch() == FALSE) {
ewprintf("Search failed: \"%s\"", pat);
return FALSE;
}
return TRUE;
}
ewprintf("No last search");
return FALSE;
}
/*
* Use incremental searching, initially in the forward direction.
* isearch ignores any explicit arguments.
*/
/*ARGSUSED*/
forwisearch(f, n)
{
return isearch(SRCH_FORW);
}
/*
* Use incremental searching, initially in the reverse direction.
* isearch ignores any explicit arguments.
*/
/*ARGSUSED*/
backisearch(f, n)
{
return isearch(SRCH_BACK);
}
/*
* Incremental Search.
* dir is used as the initial direction to search.
* ^S switch direction to forward
* ^R switch direction to reverse
* ^Q quote next character (allows searching for ^N etc.)
* <ESC> exit from Isearch
* <DEL> undoes last character typed. (tricky job to do this correctly).
* other ^ exit search, don't set mark
* else accumulate into search string
*/
isearch(dir) {
register int c;
register LINE *clp;
register int cbo;
register int success;
int pptr;
char opat[NPAT];
VOID ungetkey();
#ifndef NO_MACRO
if(macrodef) {
ewprintf("Can't isearch in macro");
return FALSE;
}
#endif
for (cip=0; cip<NSRCH; cip++)
cmds[cip].s_code = SRCH_NOPR;
(VOID) strcpy(opat, pat);
cip = 0;
pptr = -1;
clp = curwp->w_dotp;
cbo = curwp->w_doto;
is_lpush();
is_cpush(SRCH_BEGIN);
success = TRUE;
is_prompt(dir, TRUE, success);
for (;;) {
update();
switch (c = getkey(FALSE)) {
case CCHR('['):
srch_lastdir = dir;
curwp->w_markp = clp;
curwp->w_marko = cbo;
ewprintf("Mark set");
return (TRUE);
case CCHR('G'):
if (success != TRUE) {
while (is_peek() == SRCH_ACCM)
is_undo(&pptr, &dir);
success = TRUE;
is_prompt(dir, pptr < 0, success);
break;
}
curwp->w_dotp = clp;
curwp->w_doto = cbo;
curwp->w_flag |= WFMOVE;
srch_lastdir = dir;
(VOID) ctrlg(FFRAND, 0);
(VOID) strcpy(pat, opat);
return ABORT;
case CCHR(']'):
case CCHR('S'):
if (dir == SRCH_BACK) {
dir = SRCH_FORW;
is_lpush();
is_cpush(SRCH_FORW);
success = TRUE;
}
if (success==FALSE && dir==SRCH_FORW)
break;
is_lpush();
pptr = strlen(pat);
(VOID) forwchar(FFRAND, 1);
if (is_find(SRCH_FORW) != FALSE) is_cpush(SRCH_MARK);
else {
(VOID) backchar(FFRAND, 1);
ttbeep();
success = FALSE;
}
is_prompt(dir, pptr < 0, success);
break;
case CCHR('R'):
if (dir == SRCH_FORW) {
dir = SRCH_BACK;
is_lpush();
is_cpush(SRCH_BACK);
success = TRUE;
}
if (success==FALSE && dir==SRCH_BACK)
break;
is_lpush();
pptr = strlen(pat);
(VOID) backchar(FFRAND, 1);
if (is_find(SRCH_BACK) != FALSE) is_cpush(SRCH_MARK);
else {
(VOID) forwchar(FFRAND, 1);
ttbeep();
success = FALSE;
}
is_prompt(dir, pptr < 0, success);
break;
case CCHR('H'):
case CCHR('?'):
is_undo(&pptr, &dir);
if (is_peek() != SRCH_ACCM) success = TRUE;
is_prompt(dir, pptr < 0, success);
break;
case CCHR('\\'):
case CCHR('Q'):
c = (char) getkey(FALSE);
goto addchar;
case CCHR('M'):
c = CCHR('J');
goto addchar;
default:
if (ISCTRL(c)) {
ungetkey(c);
curwp->w_markp = clp;
curwp->w_marko = cbo;
ewprintf("Mark set");
curwp->w_flag |= WFMOVE;
return TRUE;
} /* and continue */
case CCHR('I'):
case CCHR('J'):
addchar:
if (pptr == -1)
pptr = 0;
if (pptr == 0)
success = TRUE;
pat[pptr++] = c;
if (pptr == NPAT) {
ewprintf("Pattern too long");
return FALSE;
}
pat[pptr] = '\0';
is_lpush();
if (success != FALSE) {
if (is_find(dir) != FALSE)
is_cpush(c);
else {
success = FALSE;
ttbeep();
is_cpush(SRCH_ACCM);
}
} else
is_cpush(SRCH_ACCM);
is_prompt(dir, FALSE, success);
}
}
/*NOTREACHED*/
}
static VOID
is_cpush(cmd) register int cmd; {
if (++cip >= NSRCH)
cip = 0;
cmds[cip].s_code = cmd;
}
static VOID
is_lpush() {
register int ctp;
ctp = cip+1;
if (ctp >= NSRCH)
ctp = 0;
cmds[ctp].s_code = SRCH_NOPR;
cmds[ctp].s_doto = curwp->w_doto;
cmds[ctp].s_dotp = curwp->w_dotp;
}
static VOID
is_pop() {
if (cmds[cip].s_code != SRCH_NOPR) {
curwp->w_doto = cmds[cip].s_doto;
curwp->w_dotp = cmds[cip].s_dotp;
curwp->w_flag |= WFMOVE;
cmds[cip].s_code = SRCH_NOPR;
}
if (--cip <= 0)
cip = NSRCH-1;
}
static int
is_peek() {
return cmds[cip].s_code;
}
/* this used to always return TRUE (the return value was checked) */
static VOID
is_undo(pptr, dir) register int *pptr; register int *dir; {
register int redo = FALSE ;
switch (cmds[cip].s_code) {
case SRCH_BEGIN:
case SRCH_NOPR:
*pptr = -1;
case SRCH_MARK:
break;
case SRCH_FORW:
*dir = SRCH_BACK;
redo = TRUE;
break;
case SRCH_BACK:
*dir = SRCH_FORW;
redo = TRUE;
break;
case SRCH_ACCM:
default:
*pptr -= 1;
if (*pptr < 0)
*pptr = 0;
pat[*pptr] = '\0';
break;
}
is_pop();
if (redo) is_undo(pptr, dir);
}
static int
is_find(dir) register int dir; {
register int plen, odoto;
register LINE *odotp ;
odoto = curwp->w_doto;
odotp = curwp->w_dotp;
plen = strlen(pat);
if (plen != 0) {
if (dir==SRCH_FORW) {
(VOID) backchar(FFARG | FFRAND, plen);
if (forwsrch() == FALSE) {
curwp->w_doto = odoto;
curwp->w_dotp = odotp;
return FALSE;
}
return TRUE;
}
if (dir==SRCH_BACK) {
(VOID) forwchar(FFARG | FFRAND, plen);
if (backsrch() == FALSE) {
curwp->w_doto = odoto;
curwp->w_dot